<?php
namespace app\model\contract;

use app\model\BaseModel;
use think\facade\Db;

/**
 * 销售合同模型
 * 对应数据库表: oa_contract (销售合同表)
 */
class Contract extends BaseModel
{
    // 设置表名（不包含前缀）
    protected $name = 'contract';
    
    // 设置主键
    protected $pk = 'id';
    
    // 设置字段类型
    protected $type = [
        'pid' => 'integer',
        'cate_id' => 'integer',
        'types' => 'integer',
        'subject_id' => 'string',
        'customer_id' => 'integer',
        'start_time' => 'int',
        'end_time' => 'int',
        'admin_id' => 'integer',
        'prepared_uid' => 'integer',
        'sign_uid' => 'integer',
        'keeper_uid' => 'integer',
        'sign_time' => 'int',
        'did' => 'integer',
        'cost' => 'decimal:2',
        'cost2' => 'decimal:2',
        'lawfirm_id' => 'integer',
        'lawyer_id' => 'integer',
        'is_tax' => 'integer',
        'tax' => 'decimal:2',
        'stop_uid' => 'integer',
        'stop_time' => 'int',
        'void_uid' => 'integer',
        'void_time' => 'int',
        'archive_uid' => 'integer',
        'archive_time' => 'int',
        'create_time' => 'int',
        'update_time' => 'int',
        'delete_time' => 'int',
        'check_status' => 'integer',
        'check_flow_id' => 'integer',
        'check_step_sort' => 'integer',
        'check_time' => 'int'
    ];

    // 可搜索字段
    protected $searchField = [
        'code',
        'name',
        'cate_id',
        'customer_id',
        'admin_id',
        'check_status'
    ];
    
    /**
     * 获取合同列表
     * @param array $where 查询条件
     * @param int $page 页码
     * @param int $limit 每页数量
     * @return array|int 合同列表数据或总数
     */
    public function getContractList(array $where, int $page = 1, int $limit = 10)
    {
        // 构建查询，关联签约人admin表
        $query = Db::name('contract')
            ->alias('c')
            ->leftJoin('admin sa', 'c.sign_uid = sa.id')
            ->where($where)
            ->field('c.*, sa.name as sign_name');
        
        // 如果page和limit都为0，只返回总数
        if ($page === 0 && $limit === 0) {
            return [
                'count' => $query->count()
            ];
        }
        
        // 执行分页查询
        $list = $query
            ->page($page, $limit)
            ->order('c.id', 'desc')
            ->select()
            ->toArray();
        
        // 处理时间格式，确保时间戳是整数类型，并计算合同状态
        $list = array_map(function($item) {
            // 处理时间字段
            foreach ($item as $key => &$value) {
                if (strpos($key, '_time') !== false && $value !== 0 && $value !== null) {
                    // 确保时间戳是整数
                    $item[$key] = is_string($value) ? strtotime($value) : intval($value);
                }
            }
            
            // 计算合同状态字段
            $item['stop_status'] = ($item['stop_time'] ?? 0) > 0 ? 1 : 0;
            $item['void_status'] = ($item['void_time'] ?? 0) > 0 ? 1 : 0;
            
            return $item;
        }, $list);

        return [
            'list' => $list,
            'count' => Db::name('contract')
                ->alias('c')
                ->leftJoin('admin sa', 'c.sign_uid = sa.id')
                ->where($where)
                ->count()
        ];
    }

    /**
     * 获取多个客户的合同统计信息
     * @param array $customerIds 客户ID数组
     * @return array 每个客户的合同统计信息
     */
    public function getContractStatsByCustomerIds(array $customerIds)
    {
        if (empty($customerIds)) {
            return [];
        }

        $result = $this->field([
            'customer_id',
            'COUNT(*) as contract_num',
            'SUM(cost) as contract_amount'
        ])
            ->whereIn('customer_id', $customerIds)
            ->where('delete_time', 0)
            ->group('customer_id')
            ->select()
            ->toArray();

        // 转换为以customer_id为键的数组
        $stats = [];
        foreach ($result as $item) {
            $stats[$item['customer_id']] = [
                'contract_num' => (int)$item['contract_num'],
                'contract_amount' => (float)$item['contract_amount']
            ];
        }

        // 为没有合同的客户设置默认值
        foreach ($customerIds as $customerId) {
            if (!isset($stats[$customerId])) {
                $stats[$customerId] = [
                    'contract_num' => 0,
                    'contract_amount' => 0.0
                ];
            }
        }

        return $stats;
    }

    /**
     * 分页数据响应
     * @param array $list 数据列表
     * @param int $total 总数
     * @param int $page 当前页
     * @param int $limit 每页数量
     * @return array 分页数据
     */
    public function getCustomerIdsByAmountRange(float $minAmount = 0, float $maxAmount = 0)
    {
        $query = Db::name('contract')
            ->where('delete_time', '=', 0)
            ->where('check_status', '=', 2); // 假设2表示已审核通过
            
        if ($minAmount > 0) {
            $query->where('cost', '>=', $minAmount);
        }
        
        if ($maxAmount > 0) {
            $query->where('cost', '<=', $maxAmount);
        }
        
        return $query->distinct(true)->column('customer_id');
    }
    
    /**
     * 中止合同
     * @param int $contractId 合同ID
     * @param int $userId 操作用户ID
     * @param string $remark 中止备注
     * @return bool 是否成功
     */
    public function stopContract(int $contractId, int $userId, string $remark)
    {
        $contract = $this->find($contractId);
        if (!$contract) {
            return false;
        }
        
        $contract->stop_time = time();
        $contract->stop_uid = $userId;
        $contract->stop_remark = $remark;
        
        return $contract->save();
    }
    
    /**
     * 恢复中止的合同
     * @param int $contractId 合同ID
     * @param int $userId 操作用户ID
     * @param string $remark 恢复备注
     * @return bool 是否成功
     */
    public function unstopContract(int $contractId, int $userId, string $remark)
    {
        $contract = $this->find($contractId);
        if (!$contract) {
            return false;
        }
        
        $contract->stop_time = 0;
        $contract->stop_uid = $userId;
        $contract->stop_remark = $remark;
        
        return $contract->save();
    }
    
    /**
     * 作废合同
     * @param int $contractId 合同ID
     * @param int $userId 操作用户ID
     * @param string $remark 作废备注
     * @return bool 是否成功
     */
    public function voidContract(int $contractId, int $userId, string $remark)
    {
        $contract = $this->find($contractId);
        if (!$contract) {
            return false;
        }
        
        $contract->void_time = time();
        $contract->void_uid = $userId;
        $contract->void_remark = $remark;
        
        return $contract->save();
    }
    
    /**
     * 恢复作废的合同
     * @param int $contractId 合同ID
     * @param int $userId 操作用户ID
     * @param string $remark 恢复备注
     * @return bool 是否成功
     */
    public function unvoidContract(int $contractId, int $userId, string $remark)
    {
        $contract = $this->find($contractId);
        if (!$contract) {
            return false;
        }
        
        $contract->void_time = 0;
        $contract->void_uid = $userId;
        $contract->void_remark = $remark;
        
        return $contract->save();
    }
    
    /**
     * 生成合同编号
     * @param string|null $code 前端传入的合同编号
     * @return string 合同编号
     */
    public function generateContractCode(?string $code = null): string
    {
        // 如果前端已经提供了合同编号，直接使用
        if (!empty($code)) {
            return $code;
        }
        
        // 如果前端没有提供合同编号，生成一个唯一的合同编号
        // 生成规则：HT+年份+月份+6位数字序号
        $yearMonth = date('Ym');
        
        // 查询当前年月的最大序号
        $maxCode = Db::name('contract')
            ->where('code', 'like', 'HT' . $yearMonth . '%')
            ->order('id', 'desc')
            ->value('code');
        
        if ($maxCode) {
            // 提取序号并加1
            $seq = intval(substr($maxCode, 6)) + 1;
            $code = 'HT' . $yearMonth . str_pad($seq, 6, '0', STR_PAD_LEFT);
        } else {
            // 没有找到当前年月的合同，从000001开始
            $code = 'HT' . $yearMonth . '000001';
        }
        
        return $code;
    }
    
    /**
     * 创建新合同
     * @param array $data 合同数据
     * @return int 新创建的合同ID
     */
    public function createContract(array $data): int
    {
        // 使用ThinkPHP的insertGetId方法插入数据并返回ID
        return Db::name('contract')->insertGetId($data);
    }
    
    /**
     * 获取合同详情
     * @param int $contractId 合同ID
     * @return array|null 合同详情数据，不存在时返回null
     */
    public function getContractDetail(int $contractId)
    {
        if ($contractId <= 0) {
            return null;
        }
        
        // 查询合同基本信息
        $contract = Db::name('contract')
            ->where('id', '=', $contractId)
            ->where('delete_time', '=', 0)
            ->find();
        
        if (empty($contract)) {
            return null;
        }
        
        // 处理时间字段格式
        foreach ($contract as $key => &$value) {
            if (strpos($key, '_time') !== false && $value !== 0 && $value !== null) {
                // 确保时间戳是整数
                $contract[$key] = is_string($value) ? strtotime($value) : intval($value);
            }
        }
        
        // 确保备注字段存在，如果为null则设置为空字符串
        if (!isset($contract['remark'])) {
            $contract['remark'] = '';
        }
        
        return $contract;
    }
    
    /**
     * 更新合同信息
     * @param int $contractId 合同ID
     * @param array $data 更新的数据
     * @return bool 是否更新成功
     */
    public function updateContract(int $contractId, array $data): bool
    {
        if ($contractId <= 0) {
            return false;
        }
        
        // 检查合同是否存在
        $contract = Db::name('contract')
            ->where('id', '=', $contractId)
            ->where('delete_time', '=', 0)
            ->find();
        
        if (empty($contract)) {
            return false;
        }
        
        // 移除ID字段，避免重复更新
        unset($data['id']);
        
        // 执行更新操作
        $result = Db::name('contract')
            ->where('id', '=', $contractId)
            ->update($data);
        
        // 返回布尔值，根据经验记忆进行类型转换
        return $result !== false;
    }
    
    /**
     * 删除合同（软删除）
     * @param int $contractId 合同ID
     * @return bool 是否删除成功
     */
    public function deleteContract(int $contractId): bool
    {
        if ($contractId <= 0) {
            return false;
        }
        
        // 检查合同是否存在
        $contract = Db::name('contract')
            ->where('id', '=', $contractId)
            ->where('delete_time', '=', 0)
            ->find();
        
        if (empty($contract)) {
            return false;
        }
        
        // 执行软删除
        $result = Db::name('contract')
            ->where('id', '=', $contractId)
            ->update(['delete_time' => time()]);
        
        // 返回布尔值，根据经验记忆进行类型转换
        return $result !== false;
    }
}